import java.util.ArrayList;
import net.phys2d.math.Vector2f;
import net.phys2d.raw.Body;
import net.phys2d.raw.BodyList;
import net.phys2d.raw.StaticBody;
import net.phys2d.raw.World;
import net.phys2d.raw.shapes.Box;
import net.phys2d.raw.strategies.QuadSpaceStrategy;

import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.tiled.TiledMap;
import org.newdawn.slick.Animation;
import org.newdawn.slick.SpriteSheet;


public class Game  extends BasicGame {

    public static int mapWidth;
    public static int mapHeight;    
    public static float mapX = 0;
    public static float mapY = 0;
    public static int viewWidth = 400;
    public static int viewHeight = 300;
    private TiledMap map;
    public Player bleh1;
    private ArrayList<Block> obsticles = new ArrayList<Block>();
    private ArrayList<Player> entities = new ArrayList<Player>();
    protected World world = new World(
            new Vector2f(0.0f, 800.0f), 10,
            new QuadSpaceStrategy(20,5));

    public Game() { super("Box Physics"); }   

    public void init(GameContainer container) throws SlickException {




        container.setVSync(true);
        container.setShowFPS(true);
        map = new TiledMap("data/testmap.tmx");   
        mapWidth = map.getWidth() * map.getTileWidth();
        mapHeight = map.getHeight() * map.getTileHeight();

        for (int x=0;x<map.getWidth();x++)
        {
            for (int y=0;y<map.getHeight();y++)
            {
                int tileID = map.getTileId(x, y, 0);
                if (tileID > 0 && tileID != 79)
                {
                    Block body = new Block(
                            x* map.getTileWidth()+map.getTileWidth()/2,
                            y* map.getTileHeight()+map.getTileHeight()/2,
                            tileID);                    

                    world.add(body.poly);
                }
            }
        }

        entities.add(bleh1=new Player(290,180)); 
        for (int i=0;i<entities.size();i++){
            world.add(entities.get(i).poly);
        }
    }
    public void adjustCam() {

        mapX = 400 - bleh1.x;
        mapY = 300 - bleh1.y;

        if (mapX > 0) {
            mapX = 0;
        }
        if (mapY > 0) {
            mapY = 0;
        }
        if (mapX < -(mapWidth - viewWidth)) {
            mapX = -(mapWidth - viewWidth);
        }
        if (mapY < -(mapHeight - viewHeight)) {
            mapY = -(mapHeight - viewHeight);
        }
    }
    public void update(GameContainer container, int delta) throws SlickException {           
        adjustCam();

        if (container.getInput().isKeyDown(Input.KEY_LEFT)) { bleh1.poly.addForce(new Vector2f(-300,0)); }
        if (container.getInput().isKeyDown(Input.KEY_RIGHT)){ bleh1.poly.addForce(new Vector2f(300,0));  }
        if (container.getInput().isKeyDown(Input.KEY_UP))   { bleh1.poly.addForce(new Vector2f(0,-6000));}
        if (container.getInput().isKeyDown(Input.KEY_DOWN)) { bleh1.poly.addForce(new Vector2f(0,300));  } 

        for (int i=0;i<entities.size();i++){
            entities.get(i).update(delta);
        }
        world.step();
    }   

    public void render(GameContainer container, Graphics g) throws SlickException {

        // map.render(0,0);
        //map.render(bleh1.x,bleh1.y);

        map.render((int)mapX,0,0,0,100,100);

        /*
        map.render(((int) mapX % 32),
                ((int) mapY % 32),
                (int) (-mapX / 32),
                (int) (-mapY / 32),
                (viewWidth / 32) + 2,
                (viewHeight / 32) + 2,
                1, false);
         */


        g.setColor(Color.white);
        BodyList bodies = world.getBodies();       
        for (int i=0;i<bodies.size();i++) {
            Body body = bodies.get(i);
            drawBoxBody(g, body,(Box)body.getShape());           
        } 
        for (int i=0;i<entities.size();i++){
            entities.get(i).draw(g);
        }
    }

    protected void drawBoxBody(Graphics g, Body body, Box box) {
        Vector2f[] pts = box.getPoints(body.getPosition(), body.getRotation());       
        Vector2f v1 = pts[0];
        Vector2f v2 = pts[1];
        Vector2f v3 = pts[2];
        Vector2f v4 = pts[3];       
        g.setColor(Color.yellow);
        g.drawLine(v1.x, v1.y, v2.x, v2.y);
        g.drawLine(v2.x, v2.y, v3.x, v3.y);
        g.drawLine(v3.x, v3.y, v4.x, v4.y);
        g.drawLine(v4.x, v4.y, v1.x, v1.y);
    }   

    public static void main(String[] argv) {
        try {
            AppGameContainer container = new AppGameContainer(new Game(), 800, 600, false);
            container.start();
        } catch (Exception e) { e.printStackTrace(); }
    }
} 